﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace Gmantis.Controls.DataGrid
{
    [TemplatePart(Name = "Grouping", Type = typeof(DataGridGroupingPanel)),
    TemplateVisualState(Name = "Ungrouped", GroupName = "GroupsStates"),
    TemplateVisualState(Name = "Grouped", GroupName = "GroupsStates"),
    TemplatePart(Name = "Empty", Type = typeof(FrameworkElement))]
    public class DataGridGroupingPresenter : Control
    {
        // Fields
        internal FrameworkElement _elementEmpty;
        internal DataGridGroupingPanel _elementGrouping;
        internal bool _isLoaded;
        private bool _validGroups;
        internal const string EmptyElementName = "Empty";
        internal const string GroupingElementName = "Grouping";
        public static readonly DependencyProperty IsEmptyProperty = DependencyProperty.Register("IsEmpty", typeof(bool), typeof(DataGridGroupingPresenter), new PropertyMetadata(true, new PropertyChangedCallback(DataGridGroupingPresenter.OnIsEmptyPropertyChanged)));

        // Events
        public event RoutedEventHandler GroupsChanged;

        // Methods
        public DataGridGroupingPresenter()
        {
            RoutedEventHandler handler = null;
            base.DefaultStyleKey = typeof(DataGridGroupingPresenter);
            if (handler == null)
            {
                handler = (param0, param1) => this.ChangeVisualStateGroups(false);
            }
            base.Loaded += handler;
            this.SetCustomDefaultValues();
        }

        protected void ChangeVisualStateGroups(bool useTransitions)
        {
            if (!this.IsEmpty)
            {
                VisualStateHelper.GoToState(this, "Grouped", useTransitions);
            }
            if (this.IsEmpty)
            {
                VisualStateHelper.GoToState(this, "Ungrouped", useTransitions);
            }
        }

        private void ClearGroups()
        {
            if (!DesignerProperties.GetIsInDesignMode(this) && (this.Panel != null))
            {
                this.Panel.Children.Clear();
            }
        }

        internal int GetIndicatorIndexFromPoint(Point mousePos)
        {
            if (((mousePos.X < 0.0) || (mousePos.Y < 0.0)) || ((mousePos.X > base.RenderSize.Width) || (mousePos.Y > base.RenderSize.Height)))
            {
                return -1;
            }
            if (this.IsEmpty)
            {
                return 0;
            }
            int num = 0;
            foreach (DataGridGroupColumnHeaderPresenter presenter in this.Panel.Children)
            {
                Point point2 = new Point();
                Point point = presenter.TransformToVisual(this).Transform(point2);
                if (mousePos.X < (point.X + (presenter.ActualWidth / 2.0)))
                {
                    return num;
                }
                num++;
            }
            return num;
        }

        internal Rect? GetIndicatorPositionFromPoint(Point mousePos)
        {
            if (((mousePos.X < 0.0) || (mousePos.Y < 0.0)) || ((mousePos.X > base.RenderSize.Width) || (mousePos.Y > base.RenderSize.Height)))
            {
                return null;
            }
            if (this.IsEmpty)
            {
                Point point = this._elementEmpty.TransformToVisual(this).Transform(new Point());
                return new Rect(point.X - this.Panel.ColumnsHeaderGap, point.Y, this.Panel.ColumnsHeaderGap, this._elementEmpty.ActualHeight);
            }
            Rect? nullable = null;
            foreach (DataGridGroupColumnHeaderPresenter presenter in this.Panel.Children)
            {
                Point point4 = new Point();
                Point point2 = presenter.TransformToVisual(this).Transform(point4);
                if (mousePos.X < (point2.X + (presenter.ActualWidth / 2.0)))
                {
                    return new Rect(point2.X - this.Panel.ColumnsHeaderGap, point2.Y, this.Panel.ColumnsHeaderGap, presenter.ActualHeight);
                }
                nullable = new Rect(point2.X + presenter.ActualWidth, point2.Y, this.Panel.ColumnsHeaderGap, presenter.ActualHeight);
            }
            return nullable;
        }

        private T GetTemplateChild<T>(string childName, bool required, ref string errors) where T : class
        {
            DependencyObject templateChild = base.GetTemplateChild(childName);
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "template part", childName, templateChild, required, ref errors);
            return (templateChild as T);
        }

        private static Storyboard GetTemplateChildResource(FrameworkElement root, string resourceName, bool required, ref string errors)
        {
            return GetTemplateChildResource<Storyboard>(root, resourceName, required, ref errors);
        }

        private static T GetTemplateChildResource<T>(FrameworkElement root, string resourceName, bool required, ref string errors) where T : class
        {
            object child = root.Resources[resourceName];
            ApplyTemplateHelper.VerifyTemplateChild(typeof(T), "resource", resourceName, child, required, ref errors);
            return (child as T);
        }

        private void InitializeEmptyPart()
        {
        }

        private void InitializeGroupingPart()
        {
            this._elementGrouping.View = this.View;
        }

        internal void InvalidateGroups()
        {
            this._validGroups = false;
            this.ClearGroups();
            base.InvalidateMeasure();
        }

        private void LoadGroups()
        {
            if (!DesignerProperties.GetIsInDesignMode(this) && (this.Panel != null))
            {
                this.Panel.Children.Clear();
                foreach (DataGridColumn column in this.View.Model.GroupManager.GroupedColumns)
                {
                    this.Panel.Children.Add(column.ViewColumn.GetGroupHeaderPresenter(true));
                }
                this.IsEmpty = this.View.Model.GroupManager.GroupedColumns.Length == 0;
                this._validGroups = true;
                if (this.GroupsChanged != null)
                {
                    this.GroupsChanged(this, new RoutedEventArgs());
                }
            }
        }

        protected override Size MeasureOverride(Size constraint)
        {
            if (!this._validGroups)
            {
                this.LoadGroups();
            }
            return base.MeasureOverride(constraint);
        }

        public override void OnApplyTemplate()
        {
            string errors = string.Empty;
            base.OnApplyTemplate();
            this._isLoaded = true;
            this._elementGrouping = this.GetTemplateChild<DataGridGroupingPanel>("Grouping", true, ref errors);
            if (this._elementGrouping != null)
            {
                this.InitializeGroupingPart();
            }
            this._elementEmpty = this.GetTemplateChild<FrameworkElement>("Empty", true, ref errors);
            if (this._elementEmpty != null)
            {
                this.InitializeEmptyPart();
            }
            if (!string.IsNullOrEmpty(errors))
            {
                this._isLoaded = false;
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to DataGridGroupingPresenter.\nDetails: {0}", new object[] { errors }));
                }
            }
            else
            {
                this.ChangeVisualStateGroups(false);
            }
        }

        private static void OnIsEmptyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DataGridGroupingPresenter).ChangeVisualStateGroups(true);
        }

        private void SetCustomDefaultValues()
        {
            base.IsTabStop = false;
        }

        // Properties
        internal DataGrid DataGrid
        {
            get
            {
                return this.View.DataGrid;
            }
        }

        public bool IsEmpty
        {
            get
            {
                return (bool)base.GetValue(IsEmptyProperty);
            }
            set
            {
                base.SetValue(IsEmptyProperty, value);
            }
        }

        public DataGridGroupingPanel Panel
        {
            get
            {
                return this._elementGrouping;
            }
        }

        internal DataGridView View { get; set; }
    }
}
